package com.zxy.zxyrpc.springboot.starter.bootstrap;

import cn.hutool.core.util.StrUtil;
import com.zxy.zxyrpc.RpcApplication;
import com.zxy.zxyrpc.config.RpcConfig;
import com.zxy.zxyrpc.exception.RpcException;
import com.zxy.zxyrpc.model.ErrorCode;
import com.zxy.zxyrpc.model.ReferenceService;
import com.zxy.zxyrpc.proxy.ServiceProxyFactory;
import com.zxy.zxyrpc.springboot.starter.annotation.RpcReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Field;

/**
 * RPC 服务消费者启动
 * 在需要 RpcReference 服务的类中，注入其代理对象
 *
 * @author zxy
 * @since 2025/5/30
 **/
@Slf4j
public class RpcConsumerBootStrap implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 获取字段信息
        Class<?> beanClass = bean.getClass();
        Field[] fields = beanClass.getDeclaredFields();

        for (Field field : fields) {
            // 获取字段上的 RpcReference 信息
            RpcReference rpcReference = field.getAnnotation(RpcReference.class);
            if (rpcReference != null) {
                // 为属性生成代理对象
                Class<?> interfaceClass = rpcReference.interfaceClass();
                // 默认值处理
                if (interfaceClass == void.class)
                    // 默认当前类为服务实现类（引用和实现同名）
                    interfaceClass = field.getType();
                // 构建代理对象
                Object proxy;
                if (rpcReference.mock()) {
                    proxy = ServiceProxyFactory.getMockProxy(interfaceClass);
                } else {
                    field.setAccessible(true);
                    // Rpc其他信息
                    RpcConfig rpcConfig = RpcApplication.getRpcConfig();
                    ReferenceService referenceService = ReferenceService.builder()
                            .serviceVersion(StrUtil.isEmpty(rpcReference.serviceVersion()) ? rpcConfig.getVersion() : rpcReference.serviceVersion())
                            .loadBalancer(StrUtil.isEmpty(rpcReference.loadBalancer()) ? rpcConfig.getLoadBalancer() : rpcReference.loadBalancer())
                            .retryStrategy(StrUtil.isEmpty(rpcReference.retryStrategy()) ? rpcConfig.getRetryStrategy() : rpcReference.retryStrategy())
                            .tolerantStrategy(StrUtil.isEmpty(rpcReference.tolerantStrategy()) ? rpcConfig.getTolerantStrategy() : rpcReference.tolerantStrategy())
                            .build();
                    proxy = ServiceProxyFactory.getProxy(interfaceClass, referenceService);
                }
                try {
                    field.set(bean, proxy);
                    field.setAccessible(false);
                } catch (IllegalAccessException e) {
                    throw new RpcException(ErrorCode.PARAMS_ERROR, "为字段注入代理对象失败");
                }
            }
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}